package org.jsola.hr.service.excel;

import com.alibaba.excel.context.AnalysisContext;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.jsola.common.BeanKit;
import org.jsola.exception.ParamException;
import org.jsola.hr.dto.SocCheckAddDTO;
import org.jsola.hr.dto.SocCheckItemImportDTO;
import org.jsola.hr.service.IEmpInfoService;
import org.jsola.hr.service.ISocCheckService;
import org.jsola.hr.vo.SocCheckParseImportListVO;
import org.jsola.hr.vo.excel.ParseResultVO;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;


/**
 * @author lyh
 */
@Slf4j
@Data
@EqualsAndHashCode(callSuper = true)
public class SocCheckImportListener extends BaseAnalysisEventListener<SocCheckItemImportDTO> {

    /**
     * 错误校验 "不能为空"
     */
    private static final String NOT_NULL = "不能为空";
    /**
     * 错误校验 "格式不正确"
     */
    private static final String FORMAT_ERROR = "格式不正确";

    /**
     * 姓名
     */
    private static final String NAME = "姓名";

    /**
     * 身份证号
     */
    private static final String ID_CARD = "身份证号";

    /**
     * 缴费类型
     */
    private static final String PAY_COST_TYPE = "缴费类型";

    /**
     * 所属年月
     */
    private static final String BELONGS_DATE = "参保月份";

    /**
     * 个人社保金额
     */
    private static final String PERSONAL_SOC_AMOUNT = "个人社保金额";

    /**
     * 公司社保金额
     */
    private static final String COMPANY_SOC_AMOUNT = "公司社保金额";

    /**
     * 个人公积金
     */
    private static final String PERSONAL_PF_AMOUNT = "个人公积金";

    /**
     * 公司公积金
     */
    private static final String COMPANY_PF_AMOUNT = "公司公积金";

    /**
     * 分隔符
     */
    private static final String COMMA = " ";

    /**
     * 校验所属年月长度
     */
    private static final Integer BELONGS_DATE_LENGTH = 6;

    /**
     * 最大入库数量
     */
    private static final int BATCH_COUNT = 3000;

    /**
     * 解析Excel结果
     */
    private List<SocCheckParseImportListVO> parseList = new ArrayList<>();

    /**
     * 入库所需要的参数
     */
    private SocCheckAddDTO socCheckAddDTO;

    @Override
    public void saveData() {
        if (dataList.size() == 0) {
            log.warn("没有数据需要入库");
            return;
        }
        log.info("{}条数据，开始存储数据库！", dataList.size());
        for (SocCheckItemImportDTO socCheckItemImportDTO : dataList) {
            if (StringUtils.isEmpty(socCheckItemImportDTO.getServiceCost())) {
                socCheckItemImportDTO.setServiceCost("0");
            }
            if (StringUtils.isEmpty(socCheckItemImportDTO.getSocialSecurityFine())) {
                socCheckItemImportDTO.setSocialSecurityFine("0");
            }
            if (StringUtils.isEmpty(socCheckItemImportDTO.getAccumulationFundFine())) {
                socCheckItemImportDTO.setAccumulationFundFine("0");
            }
        }
        BeanKit.getBean(ISocCheckService.class).saveExcelDate(dataList, socCheckAddDTO, tokenUser);
    }

    @Override
    public void invoke(SocCheckItemImportDTO data, AnalysisContext context) {
        // 如果是只解析，则解析后返回
        if (parseOnly) {
            parse(data, context);
        } else {
            dataList.add(data);
            if (dataList.size() >= BATCH_COUNT) {
                // 入库
                saveData();
                // 存储完成清理 list
                dataList.clear();
            }
        }
    }

    /**
     * 表头处理
     *
     * @param headMap 表头map
     * @param context 表头内容
     */
    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        log.info("{}", headMap);
        List<String> headList = Arrays.asList(
                "姓名",
                "身份证号",
                "缴费类型",
                "参保月份",
                "个人社保费",
                "单位社保费",
                "个人公积金",
                "单位公积金",
                "服务费");
        for (Integer integer : headMap.keySet()) {
            String head = headMap.get(integer);
            if (!headList.contains(head)) {
                throw new ParamException("检测模板不正确（请查看模板表头）");
            }
        }
    }

    @Override
    protected ParseResultVO<SocCheckItemImportDTO> parse(SocCheckItemImportDTO data, AnalysisContext context) {
        ParseResultVO<SocCheckItemImportDTO> parseResultVO = new ParseResultVO<>();
        // 当前行号
        SocCheckParseImportListVO parse = data.to(SocCheckParseImportListVO.class);
        StringBuilder stringBuilder = new StringBuilder();
        if (StringUtils.isEmpty(data.getName())) {
            parse.setParseResult(false);
            stringBuilder.append(NAME + NOT_NULL + COMMA);
        }
        if (StringUtils.isEmpty(data.getIdCard())) {
            parse.setParseResult(false);
            stringBuilder.append(ID_CARD + NOT_NULL + COMMA);
        }
        if (StringUtils.isEmpty(data.getBelongsDate())) {
            parse.setParseResult(false);
            stringBuilder.append(BELONGS_DATE + NOT_NULL + COMMA);
        } else {
            try {
                new BigDecimal(data.getBelongsDate());
                if (!BELONGS_DATE_LENGTH.equals(data.getBelongsDate().length())) {
                    parse.setParseResult(false);
                    stringBuilder.append(BELONGS_DATE + FORMAT_ERROR + COMMA);
                }
            } catch (Exception e) {
                parse.setParseResult(false);
                stringBuilder.append(BELONGS_DATE + FORMAT_ERROR + COMMA);
            }
        }
        if (StringUtils.isEmpty(data.getPayCostType())) {
            parse.setParseResult(false);
            stringBuilder.append(PAY_COST_TYPE + NOT_NULL + COMMA);
        }
        if (StringUtils.isEmpty(data.getPersonalSocAmount())) {
            parse.setParseResult(false);
            stringBuilder.append(PERSONAL_SOC_AMOUNT + NOT_NULL + COMMA);
        } else {
            try {
                new BigDecimal(data.getPersonalSocAmount());
            } catch (Exception e) {
                parse.setParseResult(false);
                stringBuilder.append(PERSONAL_SOC_AMOUNT + FORMAT_ERROR + COMMA);
            }
        }
        if (StringUtils.isEmpty(data.getCompanySocAmount())) {
            parse.setParseResult(false);
            stringBuilder.append(COMPANY_SOC_AMOUNT + NOT_NULL + COMMA);
        } else {
            try {
                new BigDecimal(data.getCompanySocAmount());
            } catch (Exception e) {
                parse.setParseResult(false);
                stringBuilder.append(COMPANY_SOC_AMOUNT + FORMAT_ERROR + COMMA);
            }
        }
        if (StringUtils.isEmpty(data.getPersonalPfAmount())) {
            parse.setParseResult(false);
            stringBuilder.append(PERSONAL_PF_AMOUNT + NOT_NULL + COMMA);
        } else {
            try {
                new BigDecimal(data.getPersonalPfAmount());
            } catch (Exception e) {
                parse.setParseResult(false);
                stringBuilder.append(PERSONAL_PF_AMOUNT + FORMAT_ERROR + COMMA);
            }
        }
        if (StringUtils.isEmpty(data.getCompanyPfAmount())) {
            parse.setParseResult(false);
            stringBuilder.append(COMPANY_PF_AMOUNT + NOT_NULL + COMMA);
        } else {
            try {
                new BigDecimal(data.getCompanyPfAmount());
            } catch (Exception e) {
                parse.setParseResult(false);
                stringBuilder.append(COMPANY_PF_AMOUNT + FORMAT_ERROR + COMMA);
            }
        }
        parse.setParseRemark(stringBuilder.toString());
        parseList.add(parse);
        return parseResultVO;
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据，确保最后遗留的数据也存储到数据库
        // 但是只解析的话不需要入库
        if (!parseOnly) {
            saveData();
        }
    }
}
